---
title: 开发者工具栏应用 API
i18nReady: true
---
import Since from '~/components/Since.astro';
import RecipeLinks from "~/components/RecipeLinks.astro";

Astro 开发者工具栏应用 API 允许你创建 [Astro 集成](/zh-cn/reference/integrations-reference/)，以便在 Astro 开发者工具栏中添加应用。这使你可以添加新功能并与第三方服务进行集成。

<RecipeLinks slugs={["zh-cn/recipes/making-toolbar-apps"]} />

## 开发者工具栏应用集成设置

集成可以在 [`astro:config:setup` 钩子](/zh-cn/reference/integrations-reference/#astroconfigsetup) 中向开发者工具栏添加应用。

```ts title="my-integration.js" {8-13}
/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "my-integration",
  hooks: {
    "astro:config:setup": ({ addDevToolbarApp }) => {
      addDevToolbarApp({
        id: "my-app",
        name: "My App",
        icon: "<svg>...</svg>",
        entrypoint: "./my-app.js",
      });
    },
  },
});
```

### `addDevToolbarApp()`

这是一个可用于 [`astro:config:setup` 钩子](/zh-cn/reference/integrations-reference/#astroconfigsetup) 的函数，用于添加开发者工具栏应用。它接受一个对象，该对象包含定义工具栏应用所需的以下属性：[`id`](#id)、[`name`](#name)、[`icon`](#icon) 和 [`entrypoint`](#entrypoint)。

### `id`

应用的唯一标识符。这将用于在钩子和事件中唯一的标识应用。

```ts title="my-integration.js" {2}
{
  id: '我的应用',
  // ...
}
```

### `name`

应用的名称。每当需要使用人类可读的名称引用应用时，都会向用户显示此名称。

```ts title="my-integration.js" {3}
{
  // ...
  name: '我的应用',
  // ...
}
```

### `icon`

用于在工具栏中显示应用的图标。可以是 [图标列表](#图标) 中的图标，或包含图标 SVG 标记的字符串。

```ts title="my-integration.js" {3}
{
  // ...
  icon: '<svg>...</svg>', // 或例如 'astro:logo'
  // ...
}
```

### `entrypoint`

导出开发者工具栏应用的文件路径。

```ts title="my-integration.js" {3}
{
  // ...
  entrypoint: './my-app.js',
}
```

<p><Since v="5.0.0" /></p>

该函数也接受 `URL` 来作为 `entrypoint`：

```ts title="my-integration.js" "new URL("./my-app.js", import.meta.url)"
/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "my-integration",
  hooks: {
    "astro:config:setup": ({ addDevToolbarApp }) => {
      addDevToolbarApp({
        id: "my-app",
        name: "My App",
        icon: "<svg>...</svg>",
        entrypoint: new URL("./my-app.js", import.meta.url),
      });
    },
  },
});
```

## 开发者工具栏应用的结构

开发者工具栏应用是一个 `.js` 或 `.ts` 文件，它默认导出一个对象，该对象使用来自 `astro/toolbar` 模块的 [`defineToolbarApp()` 函数](#definetoolbarapp)。

```ts title="src/my-app.js"
import { defineToolbarApp } from "astro/toolbar";

export default defineToolbarApp({
  init(canvas) {
    const text = document.createTextNode('Hello World!');
    canvas.appendChild(text);
  },
  beforeTogglingOff() {
    const confirmation = window.confirm('Really exit?');
    return confirmation;
  } 
});
```
### `defineToolbarApp()`

<p><Since v="4.7.0" /></p>

一个在你的工具栏应用加载和关闭时定义逻辑的函数。

此函数接收一个对象，其中包含一个 [`init()`](#init) 函数，该函数将在开发者工具栏应用加载时被调用。它还可以包含一个 [`beforeTogglingOff()`](#beforetogglingoff) 函数，该函数将在点击工具栏应用以关闭其活动状态时运行。

### `init()`

**签名：** `init(canvas: ShadowRoot, app: ToolbarAppEventTarget, server: ToolbarServerHelpers) => void`

虽然不是必需的，但大多数应用会使用这个函数来定义应用的核心行为。这个函数只会在应用加载时被调用一次，具体是在浏览器空闲时或用户在 UI 中点击应用时，具体取决于哪个先发生。

该函数接收三个参数来定义你的应用逻辑：[`canvas`](#canvas)（用于向屏幕渲染元素），[`app`](#app)（用于从开发者工具栏发送和接收客户端事件），和 [`server`](#server)（用于与服务器通信）。

#### `canvas`

一个标准的 [ShadowRoot](https://developer.mozilla.org/zh-CN/docs/Web/API/ShadowRoot)，应用可以用来渲染其 UI。可以使用标准的 DOM API 创建元素并添加到 ShadowRoot 中。

每个应用都会接收到一个专用的 ShadowRoot 用于渲染其 UI。此外，父元素使用 `position: absolute;` 进行定位，因此应用的 UI 不会影响 Astro 页面的布局。
```ts title="src/my-app.js" {3}
export default defineToolbarApp({
	init(canvas) {
    canvas.appendChild(document.createTextNode('你好，世界！'))
  }
});
```

#### `app`

<p><Since v="4.7.0" /></p>

一个标准的 [`EventTarget`](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget) ，附带一些额外的 [客户端事件](#客户端事件)，可用于从开发者工具栏发送和接收事件。

```ts title="src/my-app.js" {3-6}
export default defineToolbarApp({
  init(canvas, app) {
    app.onToggled(({ state }) => {
      const text = document.createTextNode(
        `The app is now ${state ? "enabled" : "disabled"}!`,
      );
      canvas.appendChild(text);
    });
  },
});
```

#### `server`

<p><Since v="4.7.0" /></p>

一个用于[与服务器通信](#客户端---服务器通信)的对象。

```ts title="src/my-app.js" {3-7}
export default defineToolbarApp({
  init(canvas, app, server) {
    server.send('my-message', { message: 'Hello!' });

    server.on('server-message', (data) => {
      console.log(data.message);
    });
  },
});
```

### `beforeTogglingOff()`

**签名：** `beforeTogglingOff(canvas: ShadowRoot): boolean | void`
<Since v="4.7.0" /><br/>

当用户在 UI 中点击应用图标来关闭应用时，将调用此可选函数。例如，此函数可以用于执行清理操作，或在关闭应用前要求用户确认。

如果返回 `false` 值，将取消关闭操作，应用将保持启用状态。

```ts title="src/my-app.js" {3-6}
export default defineToolbarApp({
  // ...
  beforeTogglingOff() {
    const confirmation = window.confirm('你确定要禁用这个应用吗？');
    return confirmation;
  }
});
```

#### `canvas`

应用的 ShadowRoot 可用于在关闭前渲染所需的任何 UI。与 [`init` 函数的 `canvas` 参数](#canvas) 相同。

## 客户端事件

除了 `EventTarget` 的标准方法（[`addEventListener`](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener)、[`dispatchEvent`](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/dispatchEvent)、[`removeEventListener`](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/removeEventListener) 等），[`app`](#app) 对象还包括以下方法：

### `onToggled()`

**签名：** `onToggled(callback: (options: {state: boolean})) => void`
<Since v="4.7.0" /><br/>

当用户在 UI 中点击应用图标以开启或关闭应用时，注册一个回调函数。

```ts title="src/my-app.js"
app.onToggled((options) => {
  console.log(`应用现在${options.state ? '已启用' : '已禁用'}！`);
});
```

### `onToolbarPlacementUpdated()`

**签名：** `onToolbarPlacementUpdated(callback: (options: {placement: 'bottom-left' | 'bottom-center' | 'bottom-right'})) => void`
<Since v="4.7.0" /><br/>

当用户更改 Dev Toolbar 的位置时，将触发此事件。例如，这可以用来在工具栏移动时重新定位应用的 UI。

```ts title="src/my-app.js"
app.onToolbarPlacementUpdated((options) => {
  console.log(`工具栏现在位于 ${options.placement}！`);
});
```

### `toggleState()`

**签名：** `toggleState(options: {state: boolean}) => void`
<Since v="4.7.0" /><br/>

更改应用的状态。例如，当用户在应用的 UI 中点击按钮时，可以通过编程方式启用或禁用应用。

```ts title="src/my-app.js"
app.toggleState({ state: false });
```

### `toggleNotification()`

**签名：** `toggleNotification(options: {state?: boolean, level?: 'error' | 'warning' | 'info'}) => void`
<Since v="4.7.0" /><br/>

在应用图标上切换通知。这可以用来通知用户应用需要关注，或者移除当前的通知。

```ts title="src/my-app.js"
app.toggleNotification({
  state: true,
  level: 'warning',
});
```

#### `state: boolean`

指示应用是否有针对用户的通知。当 `true` 时，应用图标将被高亮显示。相反，当 `false` 时，将移除高亮显示。如果未指定此属性，默认为 `true`。


#### `level: 'error' | 'warning' | 'info'`

指示通知的级别。这将用于确定应用图标上高亮显示的颜色和形状（深粉色圆圈、金色三角形或蓝色正方形）。如果未指定此属性，将默认为 `'error'`。

## 客户端 - 服务器通信

使用 [Vite 的客户端 - 服务器通信方法](https://cn.vite.dev/guide/api-plugin.html#client-server-communication)，Dev Toolbar Apps 和服务器可以相互通信。为了便于发送和接收自定义消息，提供了辅助方法，可在你的工具栏应用（客户端）和你的集成（服务器端）中使用。

### 在客户端

在你的应用中，使用 [`init()` 钩子上的 `server` 对象](#server) 来发送和接收服务器的消息。

```ts title="src/my-app.js" {3-7} "server"
export default defineToolbarApp({
  init(canvas, app, server) {
    server.send('my-message', { message: '你好！' });

    server.on('server-message', (data) => {
      console.log(data.message);
    });
  },
});
```

#### `send()`

**Signature:** `send<T>(event: stringify, data: T) => void`
<Since v="4.7.0" />

从你的工具栏应用中定义的逻辑发送数据到服务器。

```ts title="src/my-app.js"
init(canvas, app, server) {
  server.send('my-app:my-message', { message: '你好！' });
}
```
在从客户端向服务器发送消息时，最好在事件名称前加上应用 ID 或其他命名空间，以避免与可能正在监听消息的其他应用或其他集成发生冲突。

#### `on()`

**签名：** `on<T>(event: string, callback: (data: T) => void) => void`
<Since v="4.7.0" /><br/>

注册一个回调函数，当服务器发送带有指定事件的消息时调用此函数。

```ts title="src/my-app.js"
init(canvas, app, server) {
  server.on('server-message', (data) => {
    console.log(data.message);
  });
}
```

### 在服务器端

在一个集成中，例如[添加你的工具栏应用的集成](#开发者工具栏应用集成设置)，使用 [`astro:server:setup` 钩子](/zh-cn/reference/integrations-reference/#astroserversetup) 来访问 `toolbar` 对象，以便向你的应用发送和接收消息。

```ts title="my-integration.js" {5}
export default () => ({
  name: "my-integration",
  hooks: {
    "astro:config:setup": ({ addDevToolbarApp }) => {},
    "astro:server:setup": ({ toolbar }) => {},
  },
});
```

#### `send()`

**签名：** `send<T>(event: string, data: T) => void`
<Since v="4.7.0" /><br/>

向客户端发送数据。

```ts title="my-integration.js"
'astro:server:setup': ({ toolbar }) => {
  toolbar.send('server-message', { message: '你好！' });
},
```

#### `on()`

**签名：** `on<T>(event: string, callback: (data: T) => void) => void`
<Since v="4.7.0" /><br/>

注册一个回调函数，当客户端发送带有指定事件的消息时调用此函数。

```ts title="my-integration.js"
'astro:server:setup': ({ toolbar }) => {
  toolbar.on('my-app:my-message', (data) => {
    console.log(data.message);
  });
},
```

#### `onInitialized()`

**签名：** `onInitialized(appId: string, callback: () => void) => void`
<Since v="4.7.0" /><br/>

注册一个回调函数，当应用初始化时调用此函数。

```ts title="my-integration.js"
'astro:server:setup': ({ toolbar }) => {
  toolbar.onInitialized('my-app', () => {
    console.log('应用现在已初始化！');
  });
},
```

:::note
Vite 内置的 `connection` 事件会在 Dev Toolbar 应用初始化**之前**触发，因此不能被应用直接使用。使用 `onInitialized` 方法来确保应用完全初始化后再向其发送消息。
:::

#### `onAppToggled()`

**签名：** `onAppToggled(appId: string, callback: (options: {state: boolean}) => void) => void`
<Since v="4.7.0" /><br/>

当用户在 UI 中点击应用图标以开启或关闭应用时，注册一个回调函数。

```ts title="my-integration.js"
'astro:server:setup': ({ toolbar }) => {
  toolbar.onAppToggled('my-app', ({ state }) => {
    console.log(`应用现在已${state ? '启用' : '禁用'}！`);
  });
},
```

## 组件库

Dev Toolbar 包含一套可以用来构建具有一致外观和感觉的应用的 web 组件。

### `astro-dev-toolbar-window`

显示窗口。

组件的插槽将被用作窗口的内容。

```html
<astro-dev-toolbar-window>
  <p>我的内容</p>
</astro-dev-toolbar-window>
```

使用 JavaScript 构建窗口时，插槽内容必须放在组件的 light DOM 内。

```js
const myWindow = document.createElement('astro-dev-toolbar-window');
const myContent = document.createElement('p');
myContent.textContent = '我的内容';

// 直接在 `window` 上使用 appendChild，不要使用 `myWindow.shadowRoot`
myWindow.appendChild(myContent);
```

### `astro-dev-toolbar-button`

显示按钮。

组件的插槽将被用作按钮的内容。

```js
const myButton = document.createElement('astro-dev-toolbar-button');
myButton.textContent = '点击我！';
myButton.buttonStyle = "purple";
myButton.size = "medium";

myButton.addEventListener('click', () => {
  console.log('被点击了！');
});
```

#### `size`

按钮的大小（`small`，`medium`，`large`）。

#### `button-style`

按钮的样式（`ghost`，`outline`，`purple`，`gray`，`red`，`green`, `yellow`, `blue`）。当使用 `ghost` 时，按钮本身是不可见的，只会显示按钮的内容。

在 JavaScript 中，使用 `buttonStyle` 属性设置此属性以避免与原生 `style` 属性冲突。


#### `button-border-radius`

<p><Since v="4.8.0" /></p>

按钮的边框半径（`normal`, `rounded`）。使用 `rounded` 时，按钮将具有圆角和四周均匀的填充。

在 JavaScript 中，使用 `buttonBorderRadius` 属性设置此属性。

### `astro-dev-toolbar-badge`

显示徽章。

组件的插槽将被用作徽章的内容。

```html
<astro-dev-toolbar-badge>我的徽章</astro-dev-toolbar-badge>
```

#### `size`

徽章的大小（`small`，`large`）。

#### `badge-style`

徽章的样式（颜色）（`purple`，`gray`，`red`，`green`，`yellow`，`blue`）。

在 JavaScript 中，使用 `badgeStyle` 属性设置此属性以避免与原生 `style` 属性冲突。

### `astro-dev-toolbar-card`

显示一张卡片。指定可选的 `link` 属性使卡片像 `<a>` 元素一样行动。

当使用 JavaScript 制作卡片时，可以指定 `clickAction` 属性使卡片像 `<button>` 元素一样行动。

组件的插槽将被用作卡片的内容。

```html
<astro-dev-toolbar-card icon="astro:logo" link="https://github.com/withastro/astro/issues/new/choose">报告问题</astro-dev-toolbar-card>
```

#### `card-style`

卡片的样式（`purple`，`gray`，`red`，`green`，`yellow`，`blue`）。这些颜色只会在鼠标悬停时应用于卡片的边框上。

在 JavaScript 中，使用 `cardStyle` 属性来设置这个属性。

### `astro-dev-toolbar-toggle`

显示切换元素，作为复选框。这个元素内部是简单的包装器，围绕着原生的 `<input type="checkbox">` 元素。可以使用 `input` 属性访问复选框元素。

```ts
const toggle = document.createElement('astro-dev-toolbar-toggle');

toggle.input.addEventListener('change', (evt) => {
  console.log(`现在的切换状态是 ${evt.currentTarget.checked ? '启用' : '禁用'}!`);
});
```

### `astro-dev-toolbar-radio-checkbox`

<p><Since v="4.8.0" /></p>

展示一个单选框。类似于 `astro-dev-toolbar-toggle` 组件，这个元素是围绕原生 `<input type="radio">` 元素的简单包装器。可以通过 `input` 属性访问单选框元素。

```ts
const radio = document.createElement('astro-dev-toolbar-radio-checkbox');

radio.input.addEventListener('change', (evt) => {
  console.log(`单选框现在${evt.currentTarget.checked ? '启用' : '禁用'}了！`);
});
```

#### `toggle-style`

切换的样式（`purple`，`gray`，`red`，`green`，`yellow`，`blue`）。

在 JavaScript 中，使用 `toggleStyle` 属性来设置这个属性。

### `astro-dev-toolbar-highlight`

可以用来高亮显示页面上的元素。在大多数情况下，你会想要使用 `top`，`left`，`width` 和 `height` CSS 属性来定位和调整这个元素的大小，以匹配你想要高亮的元素。

```html
<!-- 高亮整个页面 -->
<astro-dev-toolbar-highlight style="top: 0; left: 0; width: 100%; height: 100%;"></astro-dev-toolbar-highlight>
```

```ts
const elementToHighlight = document.querySelector('h1');
const rect = elementToHighlight.getBoundingClientRect();

const highlight = document.createElement('astro-dev-toolbar-highlight');

highlight.style.top = `${Math.max(rect.top + window.scrollY - 10, 0)}px`;
highlight.style.left = `${Math.max(rect.left + window.scrollX - 10, 0)}px`;
highlight.style.width = `${rect.width + 15}px`;
highlight.style.height = `${rect.height + 15}px`;
highlight.icon = 'astro:logo';
```

#### `style`

高亮显示的样式（`purple`，`gray`，`red`，`green`，`yellow`，`blue`）。

#### `icon`

用于在高亮显示的右上角展示的 [图标](#图标)。

### `astro-dev-toolbar-tooltip`

显示带有不同 sections 的工具提示。此组件默认设置为 `display: none;`，可以使用 `data-show="true"` 属性使其可见。

使用 `sections` 属性定义 sections。此属性是具有以下形状的对象的数组：

```ts
{
	title?: string; // sections 的标题
	inlineTitle?: string; // sections 的标题，显示在标题旁边
	icon?: Icon; // sections 的图标
	content?: string; // sections 的内容
	clickAction?: () => void | Promise<void>; // 点击 sections 时执行的操作
	clickDescription?: string; // 点击 sections 时执行的操作的描述
}
```

```ts
const tooltip = document.createElement('astro-dev-toolbar-tooltip');

tooltip.sections = [{
  title: '我的部分',
  icon: 'astro:logo',
  content: '我的内容',
  clickAction: () => {
    console.log('点击了！')
  },
  clickDescription: '点击我！'
}]
```

此组件通常与 `astro-dev-toolbar-highlight` 组件结合使用，当鼠标悬停在高亮的元素上时显示工具提示：

```ts
const highlight = document.createElement('astro-dev-toolbar-highlight');

// 定位高亮...

const tooltip = document.createElement('astro-dev-toolbar-tooltip');

// 向工具提示添加部分...

highlight.addEventListener('mouseover', () => {
  tooltip.dataset.show = 'true';
});

highlight.addEventListener('mouseout', () => {
  tooltip.dataset.show = 'false';
});
```

### `astro-dev-toolbar-icon`

显示图标。可以使用 `icon` 属性指定[图标列表](#图标)中的图标，或者将图标的 SVG 标记作为插槽传递。

```html
<astro-dev-toolbar-icon icon="astro:logo" />
```

```html
<astro-dev-toolbar-icon>
  <svg>...</svg>
</astro-dev-toolbar-icon>
```

#### 图标

目前，可以在任何接受图标的组件中使用以下图标：

- `astro:logo`
- `warning`
- `arrow-down`
- `bug`
- `file-search`
- `check-circle`
- `gear`
- `lightbulb`
- `checkmark`
- `dots-three`
- `copy`

以上所有图标默认设置为 `fill="currentColor"`，并将从父元素继承其颜色。
